import type { Relationship } from '@/types/user'
import type { AjaxResponse } from 'uni-ajax'
import { useProfile } from '@/stores'
import { useConsole, useCurrentPage, useKsUrlLogin, useModal, useRelaunch, useToast } from '@/utils'
import { silenceLogin } from '@/utils/login'
import { until } from '@/utils/vueuse/until'
import { isEmpty, isNil, isPlainObject, pickBy } from 'lodash-es'
import ajax from 'uni-ajax'
import { ref } from 'vue'

import { object as zobject, string as zstring, union as zunion } from 'zod'

const isRefreshing = ref(false) // 重新登录的标识

function consoleDataGroup({ config, data, statusCode }: AjaxResponse) {
  const path = config.url!.replace(config.baseURL!, '')
  let res_data = {} as { type: 'log' | 'error', value: any }
  if (statusCode === 200) {
    res_data = { type: 'log', value: data }
  }
  else {
    res_data = { type: 'error', value: `${data.code}: ${data.msg}` }
  }
  useConsole?.group(
    `%c${config.method} ${statusCode}%c${path}`,
    `color:white;background:${[200, 204].includes(statusCode) ? 'purple' : 'red'};padding:1px 4px;margin-right:5px;border-radius:3px;`,
    '',
  )
  if (!isEmpty(config.data)) {
    useConsole?.log('⬆️', config.data)
  }
  useConsole?.[res_data.type]('⬇️', res_data.value)
  useConsole?.groupEnd()
}

async function reLogin() {
  await silenceLogin()
}

const instance = ajax.create({
  baseURL: UNI_PLATFORM === 'h5' ? '/bs-api' : import.meta.env.VITE_BASE_URL,
  // validateStatus: statusCode => statusCode >= 200 && statusCode < 300,
})

instance.interceptors.request.use((config) => {
  // config.header['content-type'] = 'application/json;charset=utf-8'

  // // 如果是 FormData 类型，设置为 multipart/form-data
  const token = uni.getStorageSync('token')
  if (!isEmpty(token)) {
    config.header.Authorization = `Bearer ${token}`
  }

  // 清除请求数据中 undefined 的 kv
  // if (isPlainObject(config.data)) {
  //   config.data = pickBy(config.data as Record<string, any>, x => !isNil(x))
  // }

  return config
})

instance.interceptors.response.use(
  async (response) => {
    if (INDEV) {
      consoleDataGroup(response)
    }
    const { statusCode, data, header, config } = response
    const code = data.code ?? statusCode
    if (!isEmpty(header?.['ahjx-new-token'])) {
      uni.setStorageSync('token', header['ahjx-new-token'])
    }
    if (statusCode === 200) {
      if ([0, 200].includes(data.code)) {
        return data.data
      }
      else if ([-1, 404].includes(data.code)) {
        await useModal({
          content: data.msg,
          showCancel: false,
          confirmText: '确定',
        })
        return Promise.reject(response)
      }
      else if ([102, 500].includes(data.code)) {
        useModal({
          title: '请求出错',
          content: data.msg,
          showCancel: false,
          confirmText: '好的',
        })
        return Promise.reject(response)
      }
      else if ([-8005, -8006].includes(data.code)) {
        // H5 直接跳转登录页
        // #ifdef H5
        useProfile().clear()
        await useModal({
          title: '请重新登录',
          content: data.msg,
          showCancel: false,
          confirmText: '确定',
        })
        useRelaunch('/me/login', {
          from: btoa(useCurrentPage().fullPath),
        })
        // #endif

        // 小程序走再次静默登录
        // #ifdef MP-WEIXIN || MP-ALIPAY || MP-TOUTIAO
        if (isRefreshing.value) {
          await until(isRefreshing).toBe(false)
        }
        else {
          isRefreshing.value = true
          await reLogin()
          isRefreshing.value = false
        }
        return instance(config)
        // #endif
        // #ifdef  MP-KUAISHOU
        const flag = useKsUrlLogin(config.url)
        if (flag) {
          useProfile().clear()
          return
        }
        useProfile().clear()
        useToast('登录超时,请重新登录')
        useRelaunch('/me/index')
        // #endif
      }
    }
    else if ([102].includes(statusCode)) {
      useModal({
        content: data.msg,
        showCancel: false,
        confirmText: '确定',
      })
      return Promise.reject(response)
    }
    else if ([403, 406].includes(code)) {
      // #ifdef H5
      useProfile().clear()
      await useModal({
        title: '请重新登录',
        content: data.msg,
        showCancel: false,
        confirmText: '确定',
      })
      useRelaunch('/me/login', {
        from: btoa(useCurrentPage().fullPath),
      })
      // #endif

      // #ifdef MP-WEIXIN || MP-ALIPAY || MP-TOUTIAO
      if (isRefreshing.value) {
        await until(isRefreshing).toBe(false)
      }
      else {
        isRefreshing.value = true
        await reLogin()
        isRefreshing.value = false
      }
      return instance(config)
      // #endif
    }
    else {
      useModal({
        title: '请求出错',
        content: data.msg,
        showCancel: false,
        confirmText: '好的',
      })
      return Promise.reject(response)
    }
  },
  (error) => {
    useConsole?.error(error)
    if (INDEV) {
      consoleDataGroup(error)
    }

    let errMsg = '请联系开发者'
    const zscheme = zobject({
      data: zunion([
        zstring().startsWith('{').endsWith('}'),
        zobject({
          error: zstring().optional(),
          msg: zstring().optional(),
        }),
      ])
        .refine((x) => {
          if (typeof x === 'string') {
            const data = JSON.parse(x)
            return 'error' in data || 'msg' in data
          }
        })
        .transform(x => typeof x === 'string' ? JSON.parse(x) : x),
    })
    const zparse = zscheme.safeParse(error)
    if (zparse.success) {
      errMsg = JSON.stringify({ error: zparse.data.data.error, msg: zparse.data.data.msg })
    }
    useModal({
      title: '请求出错',
      content: errMsg,
      showCancel: false,
      confirmText: '确定',
    })
    return Promise.reject(error)
  },
)

export default instance
